#! /usr/bin/env python
"""
::BOH
$Id: TKwatcher.py,v 1.2 2006/04/18 00:30:00

Copyright (c) 2006 George Bobeck. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
::EOH

TKwatcher.py is a non-daemon "collector".  
It listens for OWTF traffic and displays it in a GUI.
"""
import sys
import os
import string
import pickle
import thread
from socket import *
from Tkinter import *
from tkColorChooser import askcolor
from tkMessageBox import *
from tkFont import *
from tkSimpleDialog import askstring
from tkFileDialog import *

# Notes on host:
# "" = localhost, will recieve MULTICAST datagrams
# "<address>" = binds to that address.  
host = ""
port = 50000
buf = 1024
addr = (host,port)


class reading:
    def __init__(self):
        self.mid = "None" # monitor ID
        self.sid = "None" # sensor ID
        self.location = "None" # sensor location 
        self.cron = "0000-01-01 00:00:00" # Datetime Format should be YYYY-MM-DD HH:MM:SS 
        self.temp = 0.0 # temperature, OWFS default
        self.humid = 0.0 # humidity, %
        self.V1 = 0.0 # Voltage 1, extra data slot
        self.V2 = 0.0 # Voltage 2, extra data slot

    def SetMID(self,a):
        self.mid = a

    def GetMID(self):
        return self.mid

    def SetSID(self,a):
        self.sid = a

    def GetSID(self):
        return self.sid

    def SetLocation(self,a):
        self.location = a

    def GetLocation(self):
        return self.location

    def SetTime(self,a):
        self.cron = a

    def GetTime(self):
        return self.cron

    def SetTemp(self,a):
        self.temp = float(a)

    def GetTemp(self):
        return self.temp

    def SetHumid(self,a):
        self.humid = a

    def GetHumid(self):
        return self.humid

    def SetV1(self,a):
        self.V1 = a

    def GetV1(self):
        return self.V1

    def SetV2(self,a):
        self.V2 = a

    def GetV2(self):
        return self.V2

    def CtoF(self):
        cel = float( self.temp )
        ft = ( cel * ( 9.0/5.0 ) ) + 32.0
        return ft

    def FtoC(self):
        ft = float( self.temp )
        cel = ((ft - 32.0) * (5.0/9.0))
        return cel

    def CtoK(self):
        kel = self.temp + 273.18
        return kel

    def KtoC(self):
        cel = self.temp - 273.18 
        return cel

global UDPSock
global test
global filename
global FontScale
global FontScaleDefault
test = 0
filename = None
FontScale = 0
if sys.platform[:3] != 'win':
    FontScale = 3
FontScaleDefault = FontScale

def reading_printer(r):
    rout =  r.cron +"\t" + r.location + "\t" + r.sid + "\t" + str(r.temp) +"\t" +str( r.CtoF() )
    return rout

def notdone():
    showwarning("D'oh!","Not yet available")

def about():
    showinfo('About TKwatcher', 
        'TKwatcher version 1.0\n\n'
        'A GUI desktop client for OWTF.\n'
        'Written by George Bobeck.\n\n'
        'Released under the GPL License.')

def onSaveAs():
    ftypes = [('All Files', '*'),('Text Files','.txt')]
    global filename
    filename = asksaveasfilename(filetypes=ftypes)
    if filename:
        open(filename,'w').write(msg.get(0.0,END))

def onSave():
    global filename
    if filename:
        open(filename,'w').write(msg.get(0.0,END))
        info = "File has been saved to:\n"+filename 
        showinfo("OWTF! Watcher", info)
    else:
        onSaveAs()

def onOpen():
    ftypes = [('All Files', '*'),('Text Files','.txt')]
    global filename
    filename = askopenfilename(filetypes=ftypes)
    if filename:
        try:
            msg.insert(END,open(filename,'r').read())
        except:
            showerror("D'oh!","File Unable to load.")

def makemenu(win):
    top = Menu(win)
    win.config(menu=top)

    file = Menu(top)
    file.add_command(label="New", command=nuke, underline=0)#CLEAR TEXT BUFFER
    file.add_command(label="Open", command=onOpen, underline=0)#OPEN FILE, LOAD TO TEXT BUFFER
    file.add_command(label="Close", command=nuke, underline=0)#SIMILAR TO NEW
    file.add_command(label="Save As", command=onSaveAs, underline=0)# SAVE TEXT BUFFER
    file.add_command(label="Save", command=onSave, underline=0)# SAVE TEXT BUFFER
    file.add('separator')
    file.add_command(label="Quit", command=win.quit, underline=0)
    top.add_cascade(label="File", menu=file, underline=0)
    
    run = Menu(top)
    run.add_command(label="Start", command=startlp, underline=0)
    run.add_command(label="Stop", command=stoplp, underline=0)
    top.add_cascade(label="Run", menu=run, underline=0)
    
    setting = Menu(top)
    setting.add_command(label="Font Color", command=setFgColor, underline=0)
    setting.add_command(label="Background Color", command=setBgColor, underline=0)
    setting.add_command(label="Default Colors", command=resetColor, underline=0)
    setting.add('separator')
    setting.add_command(label="Networking", command=notdone, underline=0)
    top.add_cascade(label="Settings", menu=setting, underline=0)#RENAME LABEL

    help = Menu(top)
    help.add_command(label="About", command=about, underline=0)#About This Program
    top.add_cascade(label="Help", menu=help, underline=0)

def setFgColor():
    (triple,hexstr) = askcolor()
    if hexstr:
        msg.config(yscrollcommand=sbar.set,fg=hexstr)

def setBgColor():
    (triple,hexstr) = askcolor()
    if hexstr:
        msg.config(yscrollcommand=sbar.set,bg=hexstr)

def resetColor():
    msg.config(yscrollcommand=sbar.set,bg="BEIGE",fg="BLACK")

def nuke():
    msg.delete(0.0,END)
    global filename
    filename = None

def startlp():
    global lp
    global test
    lp = 1
    if test < 1:
        thread.start_new(watcher,(addr,))
        test =  1
        showinfo("OWTF! Watcher", "Watcher has been started")
    else:
        showwarning("OWTF! Watcher", "Watcher is already running.")

def stoplp():
    global test
    global lp
    if test > 0:
        lp = 0
        global UDPSock
        UDPSock.close()
        test = 0
        showinfo("OWTF! Watcher", "Watcher has been stopped")
    else:
        showwarning("OWTF! Watcher", "Watcher is not running")
    
def watcher(addr):
    global UDPSock
    UDPSock = socket(AF_INET,SOCK_DGRAM)
    UDPSock.bind(addr)
    while lp:
        data,addr = UDPSock.recvfrom(buf)
        if not data:
            showerror("D'oh!", "OOPS: Datagram Error!!")
            stoplp()
            break
        else:
            dout = reading()
            dout = pickle.loads(data)
            msg.insert(END,reading_printer(dout)+"\n")
            print reading_printer(dout)
    
if __name__  == '__main__':
    root = Tk()
    root.title("OWTF! Watcher")
    makemenu(root)
    sbar = Scrollbar(root)
    msg = Text(root)
    sbar.config(command=msg.yview)
    msg.config(yscrollcommand=sbar.set,bg='BEIGE')
    sbar.pack(side=RIGHT, fill=Y)
    msg.pack(side=LEFT, expand=YES, fill=BOTH)
    root.mainloop()
